// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) 2006 Microsoft Corporation. All rights reserved.

// Original code from the Microsoft Windows SDK for Windows Vista.

using System;
using System.Xml;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.Feeds.Interop;

/// <summary>
/// Representation of an Item element in an RSS 2.0 XML document.
/// Zero or more RssItems are contained in an RssChannel.
/// </summary>
public class RssItem : IItem
{
	private readonly string _title;
	private readonly string _description;
	private readonly string _link;
	private readonly FileInfo _enclosure;

	public string Title { get { return this._title; } }
	public string Description { get { return this._description; } }
	public string Link { get { return this._link; } }
	public FileInfo Enclosure { get { return this._enclosure; } }

	/// <summary>
	/// Build an RSSItem from an XmlNode representing an Item element inside an RSS 2.0 XML document.
	/// </summary>
	/// <param name="itemNode"></param>
	internal RssItem(XmlNode itemNode)
	{
		XmlNode selected;
		selected = itemNode.SelectSingleNode("title");
		if (selected != null)
		{
			this._title = selected.InnerText;
		}

		selected = itemNode.SelectSingleNode("description");
        if (selected != null)
        {
            this._description = selected.InnerText;
        }

		selected = itemNode.SelectSingleNode("link");
        if (selected != null)
        {
            this._link = selected.InnerText;
        }

		selected = itemNode.SelectSingleNode("enclosure/@url");
		if (selected != null)
		{
			string filename = selected.InnerText;
            if (filename != null)
            {
                this._enclosure = new FileInfo("@" + filename);
            }
		}
	}

	internal RssItem(IFeedItem item)
    {
		this._title = StripHTMLTags(item.Title);
        this._link = item.Link;

        try
        {
            this._description = StripHTMLTags(item.Description);
        }
        catch (ArgumentException)
        {
            this._description = "<<<Item text too long.>>>";
        }

        IFeedEnclosure enclosure = (IFeedEnclosure)item.Enclosure;
        if (enclosure != null)
        {
            string filename = GetLocalPath(enclosure);

            try
            {
                // Let's make sure we only add pictures.
                string extension = "*" + Path.GetExtension(filename);
                extension = extension.ToUpperInvariant();
                if (FeedList.ImageExtensions.Contains(extension))
                {
                    // Set enclosure without checking for existence, since enclosure might
                    // not be on disk yet (BITS still getting it).
                    this._enclosure = new FileInfo(filename);
                }
            }
            catch (ArgumentException)
            {
                System.Diagnostics.Debug.Print("Illegal character in filename."); 
                // 'Illegal character in filename' is one possible exception.
                // Ignore exception; since we'll skip rssItems with this.enclosure == null
                // higher up in the call chain.
            }
            catch (NotSupportedException)
            {
                System.Diagnostics.Debug.Print("The given path's format is not supported.");
                // 'Message="The given path's format is not supported."' is another possible exception.
                // Ignore exception; since we'll skip rssItems with this.enclosure == null
                // higher up in the call chain.
            }
        }
    }

	private static string GetLocalPath(IFeedEnclosure encl)
	{
		try
		{
            return encl.LocalPath;
		}
		catch (System.Runtime.InteropServices.COMException ex)
		{
			if (ex.ErrorCode == -2147024735)
			{
                System.Diagnostics.Debug.Print("Enclosure localPath is invalid.");
                // "The specified path is invalid. (Exception from HRESULT: 0x800700A1)"
				// ignore exception
			}
			else
				throw;
		}
		catch (FileNotFoundException)
		{
            System.Diagnostics.Debug.Print("Enclosure localPath element not found exception.");
            // ignore
		}
		return null;
	}

    private static string StripHTMLTags(string input)
    {
        if (null != input)
        {
            Regex rgx = new Regex("<[^>]*>", RegexOptions.Multiline);
            return rgx.Replace(input, "");
        }

        return null;
    }
}